﻿using CsvHelper;
using Python.Runtime;
using System.Globalization;

namespace PythonnetFFT
{
    public class Program
    {
        const string PathToPythonDir = "D:\\Python311";
        const string DllOfPython = "python311.dll";

        static void Main(string[] args)
        {
            // 傅里叶变换
            FFT();
        }
        /// <summary>
        /// 傅里叶变换
        /// </summary>
        static void FFT()
        {
            try
            {
                Runtime.PythonDLL = Path.Combine(PathToPythonDir, DllOfPython);
                PythonEngine.Initialize();
                using (Py.GIL())
                {
                    dynamic pd = Py.Import("pandas");
                    dynamic np = Py.Import("numpy");
                    dynamic plt = Py.Import("matplotlib.pyplot");
                    dynamic fft = Py.Import("scipy.fftpack");

                    using dynamic scope = Py.CreateScope();
                    scope.Exec(@"def get_slice(net_array): return net_array[:len(net_array)//2]");

                    // 读取数据
                    var data = pd.read_csv("clean_data_row.csv");
                    int listLength = data.__len__();
                    Console.WriteLine("读取长度:" + listLength);

                    // 进行傅里叶变换
                    var fft_result = fft.fft(data); // 对数据进行傅里叶变换
                    var frequencies = fft.fftfreq(listLength);

                    // 计算功率谱密度
                    var power_spectrum = np.square(np.abs(fft_result)) / listLength;
                    var frequencies_positive = scope.get_slice(frequencies);

                    /*
                    // 如果是api接口，直接返回x轴和y轴数据
                    double[] xAxis = frequencies.As<double[]>();
                    PyObject yAxisDatas = np.abs(fft_result);
                    double[][] yAxis = yAxisDatas.As<dynamic[]>()
                        .Select(s => (double[])s.As<double[]>())
                        .ToArray();

                    double[] xAxis2 = xAxis.Take(listLength / 2).ToArray();
                    PyObject yAxisDatas2 = power_spectrum;
                    double[][] yAxis2 = yAxisDatas2.As<dynamic[]>()
                        .Select(s => (double[])s.As<double[]>())
                        .Take(listLength / 2)
                        .ToArray();
                    */

                    // 绘制频谱图和功率谱密度图
                    plt.figure(figsize: new dynamic[] { 12, 6 });

                    // 频谱图
                    plt.subplot(1, 2, 1);
                    plt.plot(frequencies, np.abs(fft_result));
                    plt.xlabel("Frequency (Hz)");
                    plt.ylabel("Amplitude");
                    plt.title("Frequency Spectrum");

                    // 功率谱密度图
                    plt.subplot(1, 2, 2);
                    plt.plot(frequencies_positive, scope.get_slice(power_spectrum));
                    plt.xlabel("Frequency (Hz)");
                    plt.ylabel("Power");
                    plt.title("Power Spectrum Density");

                    // 布局调整，防止重叠
                    plt.tight_layout();
                    // 显示图表
                    plt.show();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("报错了：" + e.Message + "\r\n" + e.StackTrace);
            }
        }

        /// <summary>
        /// 读取CSV数据
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>文件中数据集合，都是double类型</returns>
        static List<double[]> ReadCsvWithCsvHelper(string filePath)
        {
            using (var reader = new StreamReader(filePath))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                var result = new List<double[]>();
                // 如果你的CSV文件有标题行，可以调用ReadHeader来读取它们
                csv.Read();
                csv.ReadHeader();
                while (csv.Read())
                {
                    result.Add(new double[] {
                        csv.GetField<double>(0),
                        csv.GetField<double>(1),
                        csv.GetField<double>(2),
                        csv.GetField<double>(3),
                        csv.GetField<double>(4),
                        csv.GetField<double>(5),
                    });
                }
                return result;
            }
        }
    }
}
